package util;

import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.CollectionUtils;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;

/******
 *
 *  TODO 待验证
 */
public class HttpClientUtils {
    private final static Logger LOGGER = LoggerFactory.getLogger(HttpClientUtils.class);

    private RequestConfig requestConfig = RequestConfig.custom()
            .setSocketTimeout(120000)
            .setConnectTimeout(120000)
            .setConnectionRequestTimeout(120000)
            .build();

    /**
     * post请求
     *
     * @param url  请求地址
     * @param json 参数json串
     * @return json结果
     */
    public static JSONObject postJson(String url, JSONObject json) {
        return postJson(url, null, json, false);
    }

    public static JSONObject postJson(String url, Map<String, String> headers, JSONObject json) {
        return postJson(url, headers, json, false);
    }

    public static JSONObject postJson(String url, Map<String, String> headers, JSONObject jsonParam, boolean noNeedResponse) {
        //post请求返回结果
        CloseableHttpClient httpClient = HttpClientFactory.getHttpClient();
        JSONObject jsonResult = null;
        HttpPost method = new HttpPost(url);
        try {
            // 装载请求头
            if (!CollectionUtils.isEmpty(headers)) {
                for (Entry<String, String> entry : headers.entrySet()) {
                    method.setHeader(entry.getKey(), entry.getValue());
                }
            }
            if (null != jsonParam) {
                //解决中文乱码问题
                StringEntity entity = new StringEntity(jsonParam.toString(), "utf-8");
                entity.setContentEncoding("UTF-8");
                entity.setContentType("application/json");
                method.setEntity(entity);
            }
            HttpResponse result = httpClient.execute(method);
            url = URLDecoder.decode(url, "UTF-8");
            /**请求发送成功，并得到响应**/
            if (result.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
                String str = "";
                try {
                    /**读取服务器返回过来的json字符串数据**/
                    str = EntityUtils.toString(result.getEntity());
                    if (noNeedResponse) {
                        return null;
                    }
                    /**把json字符串转换成json对象**/
                    jsonResult = JSONObject.parseObject(str);
                } catch (Exception e) {
                    LOGGER.error("POST Request Failed: " + url, e);
                }
            } else {
                method.abort();
            }
        } catch (IOException e) {
            LOGGER.error("POST Request Failed: " + url, e);
        }
        return jsonResult;
    }


    public static String postForm(String url, Map<String, Object> map) {
        return postForm(url, null, map, null);
    }

    public static String postForm(String url, Map<String, Object> map, String charset) {
        return postForm(url, null, map, charset);
    }

    public static String postForm(String url, Map<String, String> headers, Map<String, Object> map) {
        return postForm(url, headers, map, null);
    }

    public static String postForm(String url, Map<String, String> headers, Map<String, Object> map, String charset) {
        HttpClient httpClient = null;
        HttpPost httpPost = null;
        String result = null;
        try {
            httpClient = HttpClientFactory.getHttpClient();
            httpPost = new HttpPost(url);
            // 装载请求头
            if (!CollectionUtils.isEmpty(headers)) {
                for (Entry<String, String> entry : headers.entrySet()) {
                    httpPost.setHeader(entry.getKey(), entry.getValue());
                }
            }
            //设置参数
            MultipartEntityBuilder builder = MultipartEntityBuilder.create();
            Iterator iterator = map.entrySet().iterator();
            while (iterator.hasNext()) {
                Entry<String, Object> elem = (Entry<String, Object>) iterator.next();

                if (elem.getValue() instanceof File) {
                    builder.addBinaryBody(elem.getKey(), (File) elem.getValue());
                } else if (elem.getValue() instanceof InputStream) {
                    builder.addBinaryBody(elem.getKey(), (InputStream) elem.getValue());
                } else if (elem.getValue() instanceof byte[]) {
                    builder.addBinaryBody(elem.getKey(), (byte[]) elem.getValue());
                } else {
                    builder.addTextBody(elem.getKey(), String.valueOf(elem.getValue()));
                }
            }
            httpPost.setEntity(builder.build());
            HttpResponse response = httpClient.execute(httpPost);
            if (response != null) {
                HttpEntity resEntity = response.getEntity();
                if (resEntity != null) {
                    result = EntityUtils.toString(resEntity, charset);
                }
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return result;
    }


    public static JSONObject get(String url, Map<String, String> params,
                                 Map<String, String> headers, String encode) throws Exception {
        LOGGER.info("request url: " + url);
        //get请求返回结果
        JSONObject jsonResult = null;
        try {
            HttpClient client = HttpClientFactory.getHttpClient();
            //发送get请求
            HttpGet request = new HttpGet(initParams(url, params, encode));
            // 装载请求头
            if (!CollectionUtils.isEmpty(headers)) {
                for (Entry<String, String> entry : headers.entrySet()) {
                    request.setHeader(entry.getKey(), entry.getValue());
                }
            }

            HttpResponse response = client.execute(request);

            LOGGER.info("response code: " + response.getStatusLine().getStatusCode());

            /**请求发送成功，并得到响应**/
            if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
                /**读取服务器返回过来的json字符串数据**/
                String strResult = EntityUtils.toString(response.getEntity());
                /**把json字符串转换成json对象**/
                jsonResult = JSONObject.parseObject(strResult);
            } else {
                request.abort();
                LOGGER.error("GET Request Failed: " + url);
            }
        } catch (IOException e) {
            LOGGER.error("GET Request Failed: " + url, e);
        }
        return jsonResult;
    }

    public static JSONObject get(String url) throws Exception {
        return get(url, null, Charset.defaultCharset().displayName());
    }

    public static JSONObject get(String url, Map<String, String> params)
            throws Exception {
        return get(url, params, Charset.defaultCharset().displayName());
    }

    public static JSONObject get(String url, Map<String, String> params, String encode)
            throws Exception {
        return get(url, params, encode);
    }

    public static String initParams(String url, Map<String, String> params) throws Exception {
        return initParams(url, params, Charset.defaultCharset().displayName());
    }

    /**
     * 功能描述: 构造请求参数
     *
     * @return 返回类型:
     * @throws Exception
     */
    public static String initParams(String url, Map<String, String> params, String encode)
            throws Exception {
        if (null == params || params.isEmpty()) {
            return url;
        }
        StringBuilder sb = new StringBuilder(url);
        if (url.indexOf("?") == -1) {
            sb.append("?");
        }
        sb.append(map2Url(params, encode));
        return sb.toString();
    }

    /**
     * map构造QueryString
     *
     * @return 返回类型:
     * @throws Exception
     */
    public static String map2Url(Map<String, String> paramToMap, String encode)
            throws Exception {
        if (null == paramToMap || paramToMap.isEmpty()) {
            return null;
        }
        StringBuffer url = new StringBuffer();
        boolean isfist = true;
        for (Entry<String, String> entry : paramToMap.entrySet()) {
            if (isfist) {
                isfist = false;
            } else {
                url.append("&");
            }
            url.append(entry.getKey()).append("=");
            String value = entry.getValue();
            if (!StringUtils.isEmpty(value)) {
                if (!StringUtils.isEmpty(encode))
                    url.append(URLEncoder.encode(value, encode));
                else
                    url.append(value);
            }
        }
        return url.toString();
    }

}
